package com.ys.controller.api.eKnowAi;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MyConfig;
import com.ys.entity.eKnowAi.*;
import com.ys.enume.eKnowAi.EknowCodeEnum;
import com.ys.service.eKnowAi.EKnowSceneService;
import com.ys.util.baidu.ApiHttpClientUtils;
import com.ys.util.RedisUtil;
import com.ys.util.SnowflakeIdWorker;
import com.ys.util.shiro.ShiroUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
@RequestMapping("/api/inter/eKnowChatSetController")
public class ApiInterEKnowChatSetController {
	private static final Logger logger = LoggerFactory.getLogger(ApiInterEKnowChatSetController.class);

	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private ApiHttpClientUtils apiHttpUtils;

	private static String URLAPI2_0 = MyConfig.getUrlApi1_5();

	@Autowired
	private EKnowSceneService eKnowSceneService;


	/*
	 * 获取场景信息
	 */
	@PostMapping("/getEKnowSceneList")
	@ResponseBody
	public JSONObject getEKnowSceneList(HttpServletRequest request, HttpServletResponse response){
		JSONObject result = new JSONObject();
		try {
			//获取场景设置信息
			List<EKnowScene> eKnowSceneList = new EKnowScene()
					.setOrderby("A.Sort ASC")
					.queryList();
			//登录的用户ID
			String loginUserId = ShiroUtils.getUserId();

			result.put("eKnowSceneList",eKnowSceneList);
			result.put("loginUserId",loginUserId);
			result.put("code", EknowCodeEnum.ApiRetuenCode.SUCCESS);
		}catch (Exception e) {
			result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
			logger.error("逸知道获取场景信息出错：",e.getMessage(),e);
		}
		return result;
	}



	/*
	 * 获取场景配置信息
	 */
	@PostMapping("/getEKnowSceneSet")
	@ResponseBody
	public JSONObject getEKnowSceneSet(HttpServletRequest request, HttpServletResponse response,@RequestParam Map<String, Object> params){
		JSONObject result = new JSONObject();
		try {
			long sceneId = Long.parseLong(params.get("sceneId").toString());//场景id
			//获取场景设置信息
			Map<String,Object> eKnowScene = new EKnowScene()
					.setId(sceneId)
					.addField("U.UserName AS userName")
					.addLeftJoin("kjecp.dbo.TS_UserInfo U ON A.UpdateUser = U.UserId")
					.queryFirstMap();
			// 定义日期格式化的模式
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			eKnowScene.put("updateTime",sdf.format((Date)eKnowScene.get("updateTime")));
			//登录的用户ID
			String loginUserId = ShiroUtils.getUserId();

			//模型相关信息
			List<EKnowModel> modelList = new EKnowModel()
					.addLeftJoin("kjecp_eknow.dbo.EKnow_Scene_Model M ON A.Id = M.ModelId")
					.where("M.SceneId = "+ sceneId)
					.setOrderby("A.Sort ASC")
					.queryList();

			//提示词相关信息
			List<EKnowScenePromptKey> promptKeyList = new EKnowScenePromptKey()
					.setSceneId(sceneId)
					.queryList();

			//知识库相关信息
			List<EKnowKnowledgeBase> knowledgeBaseList = new EKnowKnowledgeBase()
					.addLeftJoin("kjecp_eknow.dbo.EKnow_Scene_Knowledge SK ON SK.KnowledgeBaseId = A.Id")
					.where("SK.SceneId = "+sceneId)
					.queryList();

			//从redis获取获取用户设置的角色名
			String userSetAiName = "";
			if(redisUtil.hGet("EKnowUserSetAiName"+sceneId,loginUserId)!= null && !redisUtil.hGet("EKnowUserSetAiName"+sceneId,loginUserId).equals("")){
				userSetAiName = redisUtil.hGet("EKnowUserSetAiName"+sceneId,loginUserId).toString();
			}
			eKnowScene.put("userSetAiName",userSetAiName);

			result.put("eKnowScene",eKnowScene);
			result.put("loginUserId",loginUserId);
			result.put("modelList",modelList);
			result.put("promptKeyList",promptKeyList);
			result.put("knowledgeBaseList",knowledgeBaseList);
			result.put("userSetAiName",userSetAiName);
			result.put("code", EknowCodeEnum.ApiRetuenCode.SUCCESS);
		}catch (Exception e) {
			result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
			logger.error("逸知道聊天获取场景配置信息出错：",e.getMessage(),e);
		}
		return result;
	}


	/*
	 * 获取Ai模型信息
	 */
	@PostMapping("/getEKnowModelList")
	@ResponseBody
	public JSONObject getEKnowModelList(HttpServletRequest request, HttpServletResponse response){
		JSONObject result = new JSONObject();
		try {
			//获取场景设置信息
			List<EKnowModel> eKnowModelList = new EKnowModel()
					.setOrderby("A.Sort ASC")
					.queryList();

			result.put("eKnowModelList",eKnowModelList);
			result.put("code", EknowCodeEnum.ApiRetuenCode.SUCCESS);
		}catch (Exception e) {
			result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
			logger.error("逸知道获取Ai模型信息出错：",e.getMessage(),e);
		}
		return result;
	}

	/**
	 * Ai聊天接口
	 */
	@PostMapping("/getAiChatByTest")
	@ResponseBody
	public JSONObject getAiChatByTest( HttpServletRequest request, HttpServletResponse response,@RequestParam Map<String, Object> params){
		JSONObject result = new JSONObject();
		try {
			long sceneId = Long.parseLong(params.get("sceneId").toString());//场景id
			long aiModelId = Long.parseLong(params.get("aiModelId").toString());//ai模型id;
			int knowledgeBaseIsOpen = Integer.parseInt(params.get("knowledgeBaseIsOpen").toString());//使用知识库问答配置是否开启（0关闭，1开启），若设置关闭，则默认使用知识库问答
			int isKnowledgeBaseSet = Integer.parseInt(params.get("isKnowledgeBase").toString());//标识是否用知识库问答，0否1是
			//获取对话历史记录
			JSONArray chatMessagesList = new JSONArray();
			if(params.get("chatMessages")!=null){
				chatMessagesList = JSON.parseArray(params.get("chatMessages").toString());
			}
			//ai人设
			String aiSystem  = params.get("aiSystem").toString();
			//模型默认名称
			String modelDefaultName  = params.get("modelDefaultName").toString();
			//自定义角色名称
			String userSetAiName  = params.get("userSetAiName").toString();
			//自定义角色名称是否开启，0否1是
			int modelRoleIsOpen = Integer.parseInt(params.get("modelRoleIsOpen").toString());
			//问题
			String question =params.get("question").toString();
			//无知识库问答的提示词
			String noLedgePromptKeyValue = params.get("noLedgePromptKeyValue").toString();
			String noLedgePromptKeyName = params.get("noLedgePromptKeyName").toString();
			//有知识库问答的提示词
			String withLedgePromptKeyValue = params.get("withLedgePromptKeyValue").toString();
			String withLedgePromptKeyName = params.get("withLedgePromptKeyName").toString();

			//知识库返回数
			int embeddingBackCount = Integer.parseInt(params.get("embeddingBackCount").toString());
			//知识库置信度
			float embeddingBackSource = Float.parseFloat(params.get("embeddingBackSource").toString());

			//所选知识库id列表，以“,”分割
			String knowledgeBaseIds = params.get("knowledgeBaseIds").toString();

			String loginUserId = ShiroUtils.getUserId();//登录的用户ID

			Map<String, Object> sendParams = new HashMap<>();
			String sentUrl = URLAPI2_0;
			JSONObject chatBack = new JSONObject();

			//sentUrl = sentUrl + "/api/outer/baiDuEKnowAi/ernieBotTurboChat";
			sentUrl = sentUrl + "/api/outer/baiDuEKnowAi/baiDuModelChat";
			sendParams.put("user_id",loginUserId);//提问人
			//设置ai人设
			if(aiSystem!=null && !"".equals(aiSystem)){
				if (aiSystem.contains("*")) {
					String aiName = modelDefaultName;
					if(modelRoleIsOpen==1){
						//从redis获取获取用户设置的角色名
						if(userSetAiName!= null && !userSetAiName.equals("")){
							aiName = userSetAiName;
						}
					}
					sendParams.put("system",aiSystem.replace("*", aiName));
				}else {
					sendParams.put("system",aiSystem);
				}
			}
			//接口后缀
			EKnowModel eKnowModel = new EKnowModel().setId(aiModelId).queryFirst();
			if(eKnowModel==null){
				result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
				return result;
			}
			String pathSuffix = eKnowModel.getPathSuffix();
			sendParams.put("pathSuffix",pathSuffix);


			int isKnowledgeBase = 1;//标识是否用知识库问答，0否1是
			//获取场景设置对应知识库设置
			if(knowledgeBaseIsOpen==1){//使用知识库问答配置是否开启（0关闭，1开启），若设置关闭，则默认使用知识库问答
				isKnowledgeBase = isKnowledgeBaseSet;
			}

			int embeddingTokens = 0;
			String useKnowLedge = "";

			if(isKnowledgeBase==0){//不用知识库问答
				//获取提示词信息
				List<Map<String,Object>> getScenePromptInfo = new EKnowScene()
						.addField("P.PromptContent AS promptContent")
						.addField("K.KeyName AS keyName")
						//.addField("K.IsCanSet AS isCanSet")
						.addField("SP.KeyValue AS keyValue")
						.addLeftJoin("kjecp_eknow.dbo.EKnow_Prompt P ON P.Id = 2 ")
						.addLeftJoin("kjecp_eknow.dbo.EKnow_Scene_PromptKey SP ON SP.SceneId = A.Id AND SP.KeyValue IS NOT NULL ")
						.addLeftJoin("kjecp_eknow.dbo.EKnow_PromptKey K ON SP.KeyId = K.Id")
						.where("A.Id="+sceneId)
						.queryMap();

				if(getScenePromptInfo!=null && getScenePromptInfo.size()>0) {
					String promptContent = getScenePromptInfo.get(0).get("promptContent").toString();
					String promptContentNew = promptContent.replace("{question}", params.get("question").toString());
					for (Map<String, Object> item : getScenePromptInfo) {
						if (noLedgePromptKeyValue != null && !"".equals(noLedgePromptKeyValue)) {
							promptContentNew = promptContentNew.replace("{" + noLedgePromptKeyName + "}", noLedgePromptKeyValue);
						} else {
							promptContentNew = promptContentNew.replace("{" + noLedgePromptKeyName + "}", "");
						}
					}
					question = promptContentNew;
				}


			}else {//用知识库问答
				//获取提示词信息
				List<Map<String,Object>> getScenePromptInfo = new EKnowScene()
						.addField("P.PromptContent AS promptContent")
						.addField("K.KeyName AS keyName")
						//.addField("K.IsCanSet AS isCanSet")
						.addField("SP.KeyValue AS keyValue")
						.addLeftJoin("kjecp_eknow.dbo.EKnow_Prompt P ON P.Id = 1 ")
						.addLeftJoin("kjecp_eknow.dbo.EKnow_Scene_PromptKey SP ON SP.SceneId = A.Id AND SP.KeyValue IS NOT NULL ")
						.addLeftJoin("kjecp_eknow.dbo.EKnow_PromptKey K ON SP.KeyId = K.Id")
						.where("A.Id="+sceneId)
						.queryMap();
				//获取知识库信息
				List<Map<String,Object>> getSceneKnowledgeInfo = new EKnowScene()
						.addField("K.ESIndexName As esIndexName")
						.addField("SK.KnowledgeBaseId As knowledgeBaseId")
						.addLeftJoin("kjecp_eknow.dbo.EKnow_Scene_Knowledge SK ON A.Id = SK.SceneId")
						.addLeftJoin("kjecp_eknow.dbo.EKnow_KnowledgeBase K ON K.Id = SK.KnowledgeBaseId")
						.where("SK.KnowledgeBaseId IN ("+knowledgeBaseIds+")")
						.where("A.Id="+sceneId)
						.queryMap();

				if(getScenePromptInfo!=null && getScenePromptInfo.size()>0 && getSceneKnowledgeInfo!=null && getSceneKnowledgeInfo.size()>0){
					String promptContent = getScenePromptInfo.get(0).get("promptContent").toString();
					String information = "";

					String getKnowledgeUrl = URLAPI2_0 + "/api/outer/baiDuEKnowAi/searchKnowledgeList";
					Map<String, Object> sendParamsBygetKnowledge = new HashMap<>();
					List<String> informationList = new ArrayList<>();
					informationList.add(params.get("question").toString());//问题
					List<String> indexNameList = new ArrayList<>();
					for(Map<String,Object> item : getSceneKnowledgeInfo){
						indexNameList.add(item.get("esIndexName").toString());
						//记录所用知识库id列表
						if(useKnowLedge == null || useKnowLedge.equals("")){
							useKnowLedge =  item.get("knowledgeBaseId").toString();
						}else {
							useKnowLedge = useKnowLedge + ","+ item.get("knowledgeBaseId");
						}

					}

					sendParamsBygetKnowledge.put("information",informationList);//问题
					sendParamsBygetKnowledge.put("size",embeddingBackCount);//向量数据库调用个数
					sendParamsBygetKnowledge.put("score",embeddingBackSource);//置信度
					sendParamsBygetKnowledge.put("indexNameList",indexNameList);//知识库索引名称
					//向量数据库获取向量数据接口
					JSONObject embeddingBack = apiHttpUtils.sendHttpPost(sendParamsBygetKnowledge,getKnowledgeUrl);
					if(embeddingBack.get("shardIdList")!=null){
						logger.info("向量数据库获取向量数据接口返回参数："+embeddingBack);
						embeddingTokens = Integer.parseInt(embeddingBack.get("totalTokens").toString());//向量化花费的tokens数

						String shardId = null;
						List<Map<String,Object>> shardIdList = (List<Map<String,Object>>)embeddingBack.get("shardIdList");
						String shardIdOrderBy = null;
						if(shardIdList.size()>0){
							for( Map<String,Object> item:shardIdList ){
								if(shardId == null || shardId.equals("")){
									shardId =  "'"+item.get("id").toString()+ "'";
									shardIdOrderBy = item.get("id").toString();
								}else {
									shardId = shardId + ",'"+ item.get("id").toString()+ "'";
									shardIdOrderBy = shardIdOrderBy + "," + item.get("id").toString() ;
								}
							}
							List<Map<String,Object>> getSceneKnowledgeList = new EKnowKnowledgeList()
									.addField("B.KnowledgeBaseName AS knowledgeBaseName")
									.where("A.ESId IN ("+shardId+")")
									.addLeftJoin("kjecp_eknow.dbo.EKnow_KnowledgeBase B ON B.Id = A.BaseId")
									.setOrderby("charindex(RTRIM(CAST(A.ESId AS VARCHAR(50))),'"+shardIdOrderBy+"')")
									.queryMap();
							if(getSceneKnowledgeList!=null && getSceneKnowledgeList.size()>0){
								for( Map<String,Object> eKnowKnowledgeList:getSceneKnowledgeList ){
									information = information + "-\n"+ eKnowKnowledgeList.get("information")+"\n";
								}
							}
							result.put("getSceneKnowledgeList", getSceneKnowledgeList);//获取到的知识库信息
							result.put("shardIdList", shardIdList);//获取到的知识库id、置信度信息
						}
					}

					if(!"".equals(information)){
						String promptContentNew = promptContent.replace("{information}", information)
								.replace("{question}", params.get("question").toString());
						for(Map<String,Object> item : getScenePromptInfo){
							if(withLedgePromptKeyValue!=null && !"".equals(withLedgePromptKeyValue)){
								promptContentNew = promptContentNew.replace("{"+withLedgePromptKeyName+"}", withLedgePromptKeyValue);
							}else {
								promptContentNew = promptContentNew.replace("{"+withLedgePromptKeyName+"}", "");
							}
						}
						question = promptContentNew;
					}

				}

			}
			//问题参数
			JSONObject userQuestion = new JSONObject();
			userQuestion.put("role","user");
			userQuestion.put("content",question);
			chatMessagesList.add(userQuestion);
			sendParams.put("messages",chatMessagesList);
			//对接Api接口，获取AI回答
			chatBack = apiHttpUtils.sendHttpPost(sendParams,sentUrl);


			logger.info("聊天接口返回："+chatBack);
			if(chatBack.get("error_code")!=null){
				result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
				return result;
			}
			if(chatBack!=null){
				//获取返回参数
				String baiDuChatId = (String) chatBack.get("id");//本轮对话的id(百度千帆会话Id)
				int created = Integer.parseInt(chatBack.get("created").toString()) ;//时间戳
				String answer =  chatBack.get("result").toString();//回答
				logger.info("回答："+answer);
				JSONObject usage = (JSONObject) chatBack.get("usage");//token统计信息
				int total_tokens = Integer.parseInt(usage.get("total_tokens").toString()) ;//tokens总数

				// 获取会话id
				SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
				long  chatidL = idWorker.nextId();
				double chatid = (double) chatidL;

				result.put("code", EknowCodeEnum.ApiRetuenCode.SUCCESS);
				result.put("answer", answer);
				result.put("chatId", chatid);
				result.put("baiDuChatId", baiDuChatId);
				result.put("wholeSendMsg", question);

				result.put("created", created);
				return result;
			}else {
				result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
				return result;
			}
		}catch (Exception e) {
			result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
			logger.error("Ai聊天接口出错：",e.getMessage(),e);
		}
		return result;

	}


	/**
	 * 更新场景配置接口
	 */
	@PostMapping("/updateScene")
	@ResponseBody
	public JSONObject updateScene(HttpServletRequest request, HttpServletResponse response,@RequestParam Map<String, Object> params){
		JSONObject result = new JSONObject();
		try{
			long sceneId = Long.parseLong(params.get("sceneId").toString());//场景id
			String modelDefaultName = params.get("modelDefaultName").toString();//默认角色名
			int modelRoleIsOpen = Integer.parseInt(params.get("modelRoleIsOpen").toString());//用户自定义AI角色名是否开启（0关闭，1开启）
			String aiSystem = params.get("aiSystem").toString();//AI人设
			String prologue = params.get("prologue").toString();//开场白设置
			String sorryTxt = params.get("sorryTxt").toString();//模型无法回答时的提示语
			int embeddingBackCount = Integer.parseInt(params.get("embeddingBackCount").toString());//向量数据库调用个数
			BigDecimal embeddingBackSource = new BigDecimal(params.get("embeddingBackSource").toString());//置信度（0-1），为0时表示不设置置信度
			int isLimitTimes = Integer.parseInt(params.get("isLimitTimes").toString());//是否限制用户每天对话次数（0否，1是）
			int userChatTimes = 0;
			if(isLimitTimes==1){
				userChatTimes = Integer.parseInt(params.get("userChatTimes").toString());//次数限制
			}

			int inputMax = Integer.parseInt(params.get("inputMax").toString());//提问字数限制
			int openIsNewChat = Integer.parseInt(params.get("openIsNewChat").toString());//开启聊天是否默认新会话
			int questionTemplateIsOpen = Integer.parseInt(params.get("questionTemplateIsOpen").toString());//问题模版是否开启（0否，1是）
			String questionTemplateTxt = params.get("questionTemplateTxt").toString();//问题模版文案

			String noPromptSet = params.get("noPromptSet").toString().trim();//无知识库提示词
			String withPromptSet = params.get("withPromptSet").toString().trim();//有知识库提示词

			String modelIdList = params.get("modelIdList").toString();//所选AI模型
			String ledgeBaseList = params.get("ledgeBaseList").toString();//知识库



			eKnowSceneService.updateEKnowScenePromptKey(noPromptSet,4L,sceneId);
			eKnowSceneService.updateEKnowScenePromptKey(withPromptSet,3L,sceneId);

			eKnowSceneService.delEKnowSceneModel(sceneId);
			String modelIds[] = modelIdList.split(",");
			for(String modelId:modelIds){
				eKnowSceneService.addEKnowSceneModel(sceneId,Long.parseLong(modelId));
			}
			eKnowSceneService.delEKnowSceneKnowledge(sceneId);
			String ledgeBaseIds[] = ledgeBaseList.split(",");
			for(String ledgeBaseId:ledgeBaseIds){
				eKnowSceneService.addEKnowSceneKnowledge(sceneId,Long.parseLong(ledgeBaseId));
			}

			String loginUserId = ShiroUtils.getUserId();//登录的用户ID
			String userName = ShiroUtils.getUserName();
			EKnowScene eKnowScene = new EKnowScene();
			eKnowScene.setId(sceneId);
			eKnowScene.setModelDefaultName(modelDefaultName);
			eKnowScene.setModelRoleIsOpen(modelRoleIsOpen);
			eKnowScene.setAiSystem(aiSystem);
			eKnowScene.setPrologue(prologue);
			eKnowScene.setSorryTxt(sorryTxt);
			eKnowScene.setEmbeddingBackCount(embeddingBackCount);
			eKnowScene.setEmbeddingBackSource(embeddingBackSource);
			eKnowScene.setIsLimitTimes(isLimitTimes);
			eKnowScene.setQuestionTemplateIsOpen(questionTemplateIsOpen);
			eKnowScene.setQuestionTemplateTxt(questionTemplateTxt);
			if(isLimitTimes==1){
				eKnowScene.setUserChatTimes(userChatTimes);
			}
			eKnowScene.setInputMax(inputMax);
			eKnowScene.setOpenIsNewChat(openIsNewChat);
			eKnowScene.setUpdateUser(loginUserId);

			int iSave = eKnowSceneService.update(eKnowScene);
			if(iSave>0){
				result.put("code", EknowCodeEnum.ApiRetuenCode.SUCCESS);
				result.put("userName", userName);
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				result.put("updateTime", sdf.format(new Date()));
			}else {
				result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
			}
		}catch (Exception e) {
			result.put("code", EknowCodeEnum.ApiRetuenCode.FAIL);
			logger.error("更新场景配置接口出错：",e.getMessage(),e);
		}
		return result;
	}





}